feat: implement MCP 2026-07-28 stateless protocol, task management, CIMD/OAuth 2.1 hardening, and MRTR support - #20
Merged
manish-wekan merged 59 commits intoSep 9, 2026
Conversation
Bring in PR 17 (Duffel API v2) and PR 18 (agent skills on init/upgrade).
manish-wekan
merged commit Sep 9, 2026
d2ad3a7
into
nitrocloudofficial:stateless
0 of 3 checks passed
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR implements the official Model Context Protocol (MCP)
2026-07-28specification across the NitroStack Python SDK while maintaining backward compatibility for existing 2025-era sessionful clients.It introduces protocol-era selection, official
mcp2.x integration for stateless HTTP and stdio, a task orchestration engine (TaskManager/TaskStore), multi-channel task status notification routing, hardened OAuth 2.1 and Client ID Metadata Document (CIMD) resolution, Multi-Round-Trip Requests (MRTR) for interactive elicitation, JSON Schema 2020-12 validation, W3C trace context propagation, cache hints, and a dedicated MCP 2.0 acceptance test suite.Scope: 86 files changed · +15,105 / −650 lines · 58 commits
System Architecture Diagram
flowchart TD subgraph Clients["MCP Clients"] C1["Modern MCP Client (2026-07-28)\n(NitroStudio / Claude / Cursor)"] C2["Legacy MCP Client (2025-06-18)\n(Sessionful SSE / HTTP)"] end subgraph Transport["Transport Layer (HTTP / STDIO)"] TH["Streamable HTTP (/mcp)"] TS["StdIO Transport"] SEL{"Protocol Era Selector\n(MCP_STATELESS / NITRO_MCP_PROTOCOL_VERSION)"} end subgraph Engines["HTTP / Wire Engines"] MV2["Official mcp 2.x\n(sessionless / dual-era)"] LV1["Legacy 1.x Session Manager\n(era: legacy only)"] end subgraph Security["Auth & Interception Layer"] JWT["JWT / Bearer Verification\n(Authorization / envelope auth)"] CIMD["CIMD & SSRF Resolver\n(HTTPS, RFC 6890, 5 KiB cap, RFC 9207 iss)"] SAN["Argument Sanitizer\n(strips _meta from tool arguments)"] end subgraph Tasks["Task Orchestration (SEP-2663)"] TINT["Task Wire Interceptor\n(tools/call task param, tasks/get, tasks/cancel)"] TM["TaskManager\n(lifecycle, access control, cancellation safety)"] TS_STORE[("Pluggable TaskStore\n(InMemoryTaskStore / custom)")] NR["TaskStatusRouter\n(/subscriptions/listen / legacy SSE / stdio)"] end subgraph Features["Protocol Features"] MRTR["MRTR Elicitation\n(input_required / requestState)"] SCH["JSON Schema 2020-12\n(depth-bounded, registration gate)"] OBS["Observability & Caching\n(W3C Trace Context / cache hints)"] end subgraph Registry["NitroStack Application Registry"] TOOLS["@tool handlers"] RES["@resource handlers"] PROMPTS["@prompt handlers"] WIDGETS["Widget / UI templates"] end C1 -->|"stateless HTTP (_meta / server/discover)"| TH C2 -->|"legacy JSON-RPC (initialize / Mcp-Session-Id)"| TH C1 -.->|"stdio stream"| TS C2 -.->|"stdio stream"| TS TH --> SEL TS --> SEL SEL -->|"era: auto (default) | modern"| MV2 SEL -->|"era: legacy (2025-06-18)"| LV1 MV2 --> JWT JWT --> CIMD MV2 --> TINT TINT --> TM TM <--> TS_STORE TM --> NR MV2 --> SAN MV2 --> SCH MV2 --> MRTR MV2 --> OBS SAN --> TOOLS OBS --> TOOLS OBS --> RES SCH --> PROMPTS TOOLS --> WIDGETS RES --> WIDGETSProtocol Era Support & Default Behavior
NitroStack Python features runtime protocol era resolution with
autoas the default when unset:NITRO_MCP_PROTOCOL_VERSION=auto(default):One official
mcp2.x sessionless engine serves both modern2026-07-28clients (per-request_meta,server/discover, SEP-2243 headers) and legacy 2025 clients (sessionlessinitialize— noMcp-Session-Id).NITRO_MCP_PROTOCOL_VERSION=2026-07-28(ormodern,latest,2026):Pure modern stateless MCP 2.0; legacy 2025 wire is rejected.
NITRO_MCP_PROTOCOL_VERSION=2025-06-18(orlegacy,2025,2025-11-25):Sessionful 2025-era wire via the legacy HTTP engine only.
MCP_STATELESS>NITRO_MCP_PROTOCOL_VERSION>ServerConfig.protocol_era> defaultauto.Era resolution is logged at HTTP/stdio startup with source:
mcp_stateless|env|config|default.Key Changes & Enhancements
1. Stateless Core & Protocol Versioning (SEP-2575, SEP-2567, SEP-2243)
mcp2.x integration: Bumped dependency tomcp>=2,<3; modern andautoeras mount the official v2 HTTP handler — not a second session manager on/mcp.nitrostack/protocol/version.py— dynamic resolution with documented era aliases; unknown tokens →auto.server/discoveron the HTTP engine advertising metadata, capabilities, and extensions.Mcp-Session-Idon sessionless engines; per-request_metaenvelope support.MCP-Protocol-Version,Mcp-Method,Mcp-Name,Mcp-Param-*; CORS preflight for 2026 headers; echo headers on responses./mcp/healthadvertises resolved era; header-onlypingfast path without a JSON-RPC body.2. Task Orchestration & Storage Abstraction (SEP-2663)
TaskStoreinterface andInMemoryTaskStorewith terminal-only TTL eviction fromlastUpdatedAt.TaskManager— create, progress,input_required, resume, complete, fail, cancel; pagination; cancellation safety.TaskAccessContextwith anti-enumeration (TaskNotFoundErroron mismatch).tools/callreturns immediateCreateTaskResult; rejects deprecatedtasks/resultandtasks/liston modern wire.TaskStatusRouterinnitrostack/tasks/notify.pyfans outnotifications/tasks/statusto/subscriptions/listen, legacy/sse, and stdio sessions; failed notify does not fail the task; honors task access context.3. Hardened OAuth 2.1 & CIMD Authentication (RFC 9207, RFC 7517)
Authorization, spec envelope auth slot, and vetted_meta; verified JWT before unsigned envelope claims._metaandio.modelcontextprotocol/*keys from tool arguments before handlers run.4. Multi-Round-Trip Requests (MRTR) (SEP-2322)
InputRequiredResultand MRTR helpers for multi-turn elicitation withinput_required,inputRequests, and opaquerequestState.5. JSON Schema 2020-12 & Schema Normalization (SEP-2106)
6. Cache Hints, Trace Context, Subscriptions & Stdio (SEP-2549, SEP-414)
ttlMs,cacheScope) on list/read/discover responses.traceparent,tracestate,baggage) onExecutionContext.trace.GET/POST /subscriptions/listen: SSE attach on the official v2 subscription bus with JWT-gated listen when OAuth/JWT is required.auto→ official dual-era loop;modern→ rejectsinitialize;legacy→ handshake loop.Environment Configuration
Type of Change
Verification & Testing
pytest tests/test_mcp20_*.py— 17 modules, 455 tests passedtest_mcp20_stateless_http.py)test_mcp20_blueprint.py,test_mcp20_foundation.py)test_mcp20_tasks.py,test_mcp20_task_store.py,test_mcp20_task_authorization.py)test_mcp20_oauth_cimd.py)test_mcp20_jsonrpc_wire.py,test_mcp20_contracts.py,test_mcp20_deprecated.py,test_mcp20_tool_args.py)test_mcp20_subscriptions.py,test_mcp20_concurrency.py,test_mcp20_stdio.py)test_mcp20_mrtr.py,test_mcp20_extensions_cache_observability.py)test_mcp20_acceptance.py)Checklist
CONTRIBUTING.mdImplementation notes
mcp2.x package127.0.0.1develop